home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Frameworks
/
TransSkel 3.24
/
Demos
/
C Demos
/
MultiSkel
/
MSkelRgn.c
< prev
next >
Wrap
Text File
|
1994-07-14
|
5KB
|
223 lines
/*
* TransSkel multiple-window demonstration: Region module
*
* This module handles a window in which the mouse may be clicked and
* dragged to draw rectangles. The rects so drawn are combined into
* a single region, the outline of which is drawn. Rects drawn while
* the shift key is held down are subtracted from the region.
* Double-clicking the mouse clears the display. If the window is
* resized, the region that is drawn is resized as well.
*
* BUG: should measure double-click time from mouse-up to next mouse down,
* not time between mouse-downs.
*
* 21 Apr 88 Paul DuBois
* 08 Jul 88
* - Changed outline so that it's drawn as a marquee.
* 29 Jan 89
* - Conversion for TransSkel 2.0.
* 12 Jan 91
* - Conversion for TransSkel 3.0.
*/
# include "TransSkel.h"
# include "MultiSkel.h"
static Rect rgnPortRect; /* portRect size - for detecting wind grows */
static RgnHandle selectRgn; /* current region to be drawn */
static long selectWhen; /* time of last click */
static Point selectWhere; /* location of last click */
static Pattern marqueePat = { 0x0f, 0x87, 0xc3, 0xe1, 0xf0, 0x78, 0x3c, 0x1e };
static void
MarqueeRgn (RgnHandle r)
{
PenState p;
Byte b;
short i;
GetPenState (&p);
PenPat ((ConstPatternParam) &marqueePat);
PenMode (patCopy);
FrameRgn (r);
SetPenState (&p);
b = ((char *) &marqueePat)[0]; /* shift pattern for next call */
for (i = 0; i < 7; ++i)
((char *) &marqueePat)[i] = ((char *) &marqueePat)[i+1];
((char *) &marqueePat)[7] = b;
}
/*
* While mouse is down, draw gray selection rectangle in the current
* port. Return the resultant rect in dstRect. The rect is always
* clipped to the current portRect.
*/
static void
DoSelectRect (Point startPoint, Rect *dstRect)
{
Point pt, dragPt;
Rect rClip;
GrafPtr port;
Boolean result;
PenState ps;
short i;
GetPort (&port);
rClip = port->portRect;
rClip.right -= 15;
GetPenState (&ps);
PenPat ((ConstPatternParam) &qd.gray);
PenMode (patXor);
dragPt = startPoint;
Pt2Rect (dragPt, dragPt, dstRect);
FrameRect (dstRect);
for (;;)
{
GetMouse (&pt);
if (!EqualPt (pt, dragPt)) /* mouse has moved, change region */
{
FrameRect (dstRect);
dragPt = pt;
Pt2Rect (dragPt, startPoint, dstRect);
result = SectRect (dstRect, &rClip, dstRect);
FrameRect (dstRect);
for (i = 0; i < 1000; ++i) { /* empty */ }
}
if (!StillDown ()) break;
}
FrameRect (dstRect); /* erase last rect */
SetPenState (&ps);
}
/*
* On double-click, clear window. On single click, draw gray selection
* rectangle as long as mouse is held down. If user draws non-empty rect,
* then add it to the selection region and redraw the region's outline.
* If the shift-key was down, then subtract the selection region instead
* and redraw.
*/
static pascal void
Mouse (Point pt, long t, short mods)
{
Rect r;
RgnHandle rgn;
r = rgnWind->portRect;
if (pt.h >= r.right - 15) /* must not click in right edge */
return;
if (t - selectWhen <= GetDblTime ()) /* it's a double-click */
{
selectWhen = 0L; /* don't take next click as double-click */
SetWindClip (rgnWind);
EraseRgn (selectRgn);
ResetWindClip ();
SetEmptyRgn (selectRgn); /* clear region */
}
else
{
selectWhen = t; /* update click variables */
selectWhere = pt;
DoSelectRect (pt, &r); /* draw selection rectangle */
if (!EmptyRect (&r))
{
EraseRgn (selectRgn);
selectWhen = 0L;
rgn = NewRgn ();
RectRgn (rgn, &r);
if ((mods & shiftKey) != 0) /* test shift key */
DiffRgn (selectRgn, rgn, selectRgn);
else
UnionRgn (selectRgn, rgn, selectRgn);
DisposeRgn (rgn);
}
}
}
static pascal void
Idle (void)
{
short i;
SetWindClip (rgnWind);
MarqueeRgn (selectRgn); /* draw selection region outline */
ResetWindClip (); /* restore previous clipping */
}
/*
* Redraw the current region. If the window was resized, resize
* the region to fit.
*/
static pascal void
Update (Boolean resized)
{
Rect r;
r = rgnWind->portRect;
EraseRect (&r);
if (resized)
{
rgnPortRect.right -= 15; /* don't use right edge of window */
r.right -= 15;
MapRgn (selectRgn, &rgnPortRect, &r);
rgnPortRect = rgnWind->portRect;
}
DrawGrowBox (rgnWind);
Idle ();
}
static pascal void
Activate (Boolean active)
{
DrawGrowBox (rgnWind);
if (active)
DisableItem (editMenu, 0);
else
EnableItem (editMenu, 0);
DrawMenuBar ();
}
static pascal void
Clobber (void)
{
DisposeRgn (selectRgn);
DisposeWindow (rgnWind);
}
void
RgnWindInit (void)
{
if (SkelQuery (skelQHasColorQD))
rgnWind = GetNewCWindow (rgnWindRes, nil, (WindowPtr) -1L);
else
rgnWind = GetNewWindow (rgnWindRes, nil, (WindowPtr) -1L);
if (rgnWind == (WindowPtr) nil)
return;
(void) SkelWindow (rgnWind,
Mouse, /* draw rectangles */
nil, /* ignore keyclicks */
Update,
Activate,
nil, /* no close proc */
Clobber, /* disposal proc */
Idle, /* idle proc */
false);
rgnPortRect = rgnWind->portRect;
selectRgn = NewRgn (); /* selected region empty initially */
selectWhen = 0L; /* first click can't be taken as dbl-click */
}